package com.relytosoft.mizar.media.analyze.services.service.behavior.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.relytosoft.dubhe.common.core.base.page.PageQuery;
import com.relytosoft.dubhe.common.core.exception.ServiceException;
import com.relytosoft.dubhe.common.core.utils.BeanCopyUtils;
import com.relytosoft.mizar.media.analyze.api.entity.behavior.AyLaneWithRegion;
import com.relytosoft.mizar.media.analyze.api.pojo.dto.AyLaneWithRegionDto;
import com.relytosoft.mizar.media.analyze.api.pojo.dto.AyLaneWithRegionParentDto;
import com.relytosoft.mizar.media.analyze.api.pojo.vo.AyLaneWithRegionVo;
import com.relytosoft.mizar.media.analyze.services.mapper.behavior.AyLaneWithRegionMapper;
import com.relytosoft.mizar.media.analyze.services.service.behavior.AyLaneWithRegionService;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author lj
 * @date 2022/6/7 10:27
 */
@Service
public class AyLaneWithRegionServiceImpl extends ServiceImpl<AyLaneWithRegionMapper, AyLaneWithRegion> implements AyLaneWithRegionService {
    @Override
    public IPage<AyLaneWithRegion> selectAyLaneWithRegionPageList(PageQuery pageQuery, AyLaneWithRegion ayLaneWithRegion) {
        if (StrUtil.isBlank(pageQuery.getOrderByColumn())) {
            pageQuery.setOrderByColumn("id");
            pageQuery.setIsAsc("desc");
        }
        return baseMapper.selectPageRegionList(pageQuery.build(), ayLaneWithRegion);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean addAyLaneWithRegion(AyLaneWithRegionParentDto ayLaneWithRegionParentDto) {
        List<AyLaneWithRegion> ayLaneWithRegions = getAyLaneWithRegions(ayLaneWithRegionParentDto);
        List<AyLaneWithRegionDto> ayLaneWithRegionDtoList = ayLaneWithRegionParentDto.getAyLaneWithRegionDtoList();
        if (ayLaneWithRegionDtoList.isEmpty()) {
            if (ayLaneWithRegions.isEmpty()) {
                return true;
            }
            // 删除数据
            for (AyLaneWithRegion ayLaneWithRegion : ayLaneWithRegions) {
                JSONObject jsonObject = JSONObject.parseObject(ayLaneWithRegion.getParamObj());
                jsonObject.getJSONArray("HotRegionList").clear();
                ayLaneWithRegion.setParamObj(jsonObject.toJSONString());
            }
            //TODO 是否同步更新该设备所有任务的监测区域信息，还是只更新本条任务的监测区域信息
            //批量更新数据
            return this.updateBatchById(ayLaneWithRegions);
        } else {
            //定义一个结果变量
            boolean result = false;
            List<AyLaneWithRegion> typeSameAyLaneWithRegions = new ArrayList<>();
            List<AyLaneWithRegionDto> typeNotSameAyLaneWithRegionDtoList = new ArrayList<>();
            //获取数据库中已存在的数据和未存在的数据
            getTypeSameAndNotSameAyLaneWithRegion(ayLaneWithRegions, ayLaneWithRegionDtoList, typeSameAyLaneWithRegions, typeNotSameAyLaneWithRegionDtoList);
            //已存在的数据更新
            if (!typeSameAyLaneWithRegions.isEmpty()) {
                //创建名为设置参数的方法
                setParamObj(ayLaneWithRegionDtoList, typeSameAyLaneWithRegions);
                //更新数据
                result = this.updateBatchById(typeSameAyLaneWithRegions);
            }
            //未存在的数据插入
            if (!typeNotSameAyLaneWithRegionDtoList.isEmpty()) {
                //获取需要添加的数据
                List<AyLaneWithRegion> addAyLaneWithRegions = getAyLaneWithRegions(typeNotSameAyLaneWithRegionDtoList);
                //添加数据
                result = this.saveBatch(addAyLaneWithRegions);
            }
            //TODO 是否同步更新该设备所有任务的监测区域信息，还是只更新本条任务的监测区域信息
            return result;
        }
    }

    @Override
    public List<AyLaneWithRegionVo> getByDeviceId(String deviceId) {
        //构造查询条件
        LambdaQueryWrapper<AyLaneWithRegion> wrapper = new QueryWrapper<AyLaneWithRegion>().lambda();
        wrapper
                .eq(AyLaneWithRegion::getCameraId, deviceId);
        //查询数据
        List<AyLaneWithRegion> ayLaneWithRegions = this.list(wrapper);
        //转换数据为Vo
        return BeanCopyUtils.copyList(ayLaneWithRegions, AyLaneWithRegionVo.class);
    }

    @Override
    public JSONArray getByCameraIdAndAlgorithmIdAndSubType(String cameraId, String subType) {
        List<String> list = baseMapper.selectByCameraIdAndSubType(cameraId, subType);
        //判断list只能有一个元素
        if (list.size() == 1) {
            //转换数据为JSONArray
            JSONObject jsonObject = JSONObject.parseObject(list.get(0));
            JSONArray hotRegionList = jsonObject.getJSONArray("HotRegionList");
            if (hotRegionList.isEmpty()) {
                return null;
            }
            return hotRegionList;
        } else if (list.size() > 1) {
            throw new ServiceException("同一设备，同一事件查询到多条检测区域绘制数据，请联系管理员");
        } else {
            return null;
        }
    }

    private void setParamObj(List<AyLaneWithRegionDto> ayLaneWithRegionDtoList, List<AyLaneWithRegion> typeSameAyLaneWithRegions) {
        //匹配typeSameAyLaneWithRegions和ayLaneWithRegionDtoList类型type相同的数据，并更新数据
        typeSameAyLaneWithRegions.forEach(ayLaneWithRegion -> {
            //筛选ayLaneWithRegionDtoList类型type相同的数据
            AyLaneWithRegionDto ayLaneWithRegionDto = ayLaneWithRegionDtoList
                    .stream()
                    .filter(ayLaneWithRegionDto1 -> ayLaneWithRegionDto1.getType().equals(ayLaneWithRegion.getType()))
                    .findFirst()
                    .orElse(null);
            //判断ayLaneWithRegionDto是否为空
            if (ayLaneWithRegionDto != null) {
                ayLaneWithRegion.setParamObj(ayLaneWithRegionDto.getParamObj());
            }
        });
    }

    private void getTypeSameAndNotSameAyLaneWithRegion(List<AyLaneWithRegion> ayLaneWithRegions,
                                                       List<AyLaneWithRegionDto> ayLaneWithRegionDtoList,
                                                       List<AyLaneWithRegion> typeSameAyLaneWithRegions,
                                                       List<AyLaneWithRegionDto> typeNotSameAyLaneWithRegionDtoList) {
        List<AyLaneWithRegion> collect = ayLaneWithRegions
                .stream()
                .filter(ayLaneWithRegion -> ayLaneWithRegionDtoList
                        .stream()
                        .anyMatch(ayLaneWithRegionDto -> ayLaneWithRegionDto.getType().equals(ayLaneWithRegion.getType())))
                .collect(Collectors.toList());
        //判断collect是否为空
        if (!collect.isEmpty()) {
            typeSameAyLaneWithRegions.addAll(collect);
        }
        //筛选出ayLaneWithRegionDtoList和ayLaneWithRegions类型type不相同的数据
        List<AyLaneWithRegionDto> collect1 = ayLaneWithRegionDtoList
                .stream()
                .filter(ayLaneWithRegionDto -> ayLaneWithRegions
                        .stream()
                        .noneMatch(ayLaneWithRegion -> ayLaneWithRegion.getType().equals(ayLaneWithRegionDto.getType())))
                .collect(Collectors.toList());
        //判断collect1是否为空
        if (!collect1.isEmpty()) {
            typeNotSameAyLaneWithRegionDtoList.addAll(collect1);
        }
    }


    @NotNull
    private List<AyLaneWithRegion> getAyLaneWithRegions(List<AyLaneWithRegionDto> ayLaneWithRegionDtoList) {
        //ayLaneWithRegionDtoList构造添加的集合
        return ayLaneWithRegionDtoList
                .stream()
                .map(ayLaneWithRegionDto -> {
                    AyLaneWithRegion ayLaneWithRegion = new AyLaneWithRegion();
                    ayLaneWithRegion.setCameraId(ayLaneWithRegionDto.getCameraId());
                    ayLaneWithRegion.setType(ayLaneWithRegionDto.getType());
                    ayLaneWithRegion.setParamObj(ayLaneWithRegionDto.getParamObj());
                    return ayLaneWithRegion;
                }).collect(java.util.stream.Collectors.toList());
    }

    private List<AyLaneWithRegion> getAyLaneWithRegions(AyLaneWithRegionParentDto ayLaneWithRegionParentDto) {
        //根据设备ID查询所有监测区域
        LambdaQueryWrapper<AyLaneWithRegion> wrapper = new QueryWrapper<AyLaneWithRegion>().lambda();
        wrapper.eq(AyLaneWithRegion::getCameraId, ayLaneWithRegionParentDto.getCameraId());
        //查询数据
        return this.list(wrapper);
    }
}
